package attr

import (
	"gddgame.cc/galaxy/common/dsl/game"
	"gddgame.cc/galaxy/utils"
)

//go:generate msgp

//msgp:tuple Attr
type Attr struct {
	Id       int    `json:"id" msg:"id"`
	Type     byte   `json:"type" msg:"type"`
	Key      string `json:"key" msg:"key"`
	IsData   bool   `json:"is_data" msg:"is_data"`
	IsBattle bool   `json:"is_battle" msg:"is_battle"`

	*game.DataExtend `json:"-" msg:"-"`
}

func NewAttr(provider *game.DataProvider, attr *SettingAttr) *Attr {
	ext := &Attr{
		Id:       attr.Id,
		Type:     attr.Type,
		Key:      attr.Key,
		IsData:   attr.IsData,
		IsBattle: attr.IsBattle,

		DataExtend: game.NewDataExtend(utils.ToString(attr.Id), attr.UpdateTime),
	}
	return ext
}

//msgp:tuple AttrGroup
type AttrGroup struct {
	Id int `json:"id" msg:"id"`

	Type      byte        `json:"type" msg:"type"`
	VarLength byte        `json:"varLength" msg:"varLength"`
	LogicList []AttrLogic `json:"logicList" msg:"logicList"`

	*game.DataExtend `json:"-" msg:"-"`
}

func NewAttrGroup(provider *game.DataProvider, attrGroup *SettingAttrGroup) *AttrGroup {
	ext := &AttrGroup{
		Id: attrGroup.Id,

		Type:      attrGroup.Type,
		VarLength: attrGroup.VarLength,
		LogicList: attrGroup.LogicList,

		DataExtend: game.NewDataExtend(utils.ToString(attrGroup.Id), attrGroup.UpdateTime),
	}
	return ext
}

//msgp:tuple AttrEvent
type AttrEvent struct {
	Index int   `json:"index" msg:"index"`
	Param []int `json:"param" msg:"param"`
}
type AttrAddition int

//msgp:tuple AttrEffect
type AttrEffect struct {
	Index byte `json:"index" msg:"index"`
	Value int  `json:"value" msg:"value"`
}

//msgp AttrEffectSlice
type AttrEffectSlice []AttrEffect

//msgp:tuple AttrCondition
type AttrCondition struct {
	Target  byte `json:"target" msg:"target"`
	Index   byte `json:"index" msg:"index"`
	Compute byte `json:"compute" msg:"compute"`
	Value   int  `json:"value" msg:"value"`
}

//msgp:tuple AttrCompute
type AttrCompute struct {
	Index  byte `json:"index" msg:"index"`
	Action byte `json:"action" msg:"action"`
	Target byte `json:"target" msg:"target"`
	Value  int  `json:"value" msg:"value"`
}

//msgp:tuple AttrLogic
type AttrLogic struct {
	Param         []int           `json:"param" msg:"param"`
	ConditionList []AttrCondition `json:"conditionList" msg:"conditionList"`
	ComputeList   []AttrCompute   `json:"computeList" msg:"computeList"`
}

func (slice AttrEffectSlice) ConcatMap(abilityMap game.IntAbilityMap) {
	for _, a := range slice {
		v, ok := abilityMap[int(a.Index)]
		if !ok {
			v = 0
		}
		abilityMap[int(a.Index)] = v + a.Value
	}
}

func (slice AttrEffectSlice) Merge(list []AttrEffect) AttrEffectSlice {
	for _, value := range list {
		flag := false
		for k, v := range slice {
			if v.Index == value.Index {
				flag = true
				slice[k].Value += value.Value
				break
			}
		}
		if !flag {
			slice = append(slice, value)
		}
	}
	return slice
}

func (slice AttrEffectSlice) ConcatList(ability game.IntAbilitySlice) game.IntAbilitySlice {
	for _, info := range slice {
		k := int(info.Index)
		if len(ability) < k {
			ability = append(ability, make([]int, k-len(ability)+1)...)
		}
		ability[info.Index] += info.Value
	}
	return ability
}

func (slice AttrEffectSlice) MergeArray(list []int, data *AttrData) AttrEffectSlice {
	for index, value := range list {
		flag := false
		id := data.IndexToId(index)
		for k, v := range slice {
			if v.Index == byte(id) {
				flag = true
				slice[k].Value += value
				break
			}
		}
		if !flag {
			slice = append(slice, AttrEffect{Index: byte(id), Value: value})
		}
	}
	return slice
}

func (slice AttrEffectSlice) ComputeFightPower(attrs []SettingAttr) int {
	power := 0
	for _, value := range slice {
		attr := attrs[value.Index]
		if attr.Power > 0 {
			// 80为战斗力最小单位
			power += value.Value * attr.Power
		}
	}
	return power
}

func (slice AttrEffectSlice) GenerateFightPower(attrs []SettingAttr, power int, attrRandom utils.RandomFactory) {
	base := slice.ComputeFightPower(attrs)
	// 根据目标战斗力，整体提升
	number := power / base
	indexMap := make(map[byte]int, len(slice))
	for i := 0; i < len(slice); i++ {
		slice[i].Value *= number
		indexMap[slice[i].Index] = i
	}
	// 随机部分战斗属性：一点属性=8战斗力，16点战斗力为基数随机
	need := power % base / 16
	for i := 0; i < need; i++ {
		attr := attrRandom.Random().(byte)
		value := attrs[attr].singleValue * 2
		index := indexMap[byte(attr)]
		slice[index].Value += value
	}
}

func (slice AttrEffectSlice) GenerateAttr() []interface{} {
	r := make([]interface{}, len(slice)*2)
	for index, k := range slice {
		r[index*2] = k.Index
		r[index*2+1] = k.Value
	}
	return r
}
func (slice AttrEffectSlice) GenerateAttrWithInt() game.IntAbilitySlice {
	r := make([]int, len(slice)*2)
	for index, k := range slice {
		r[index*2] = utils.ToInt(k.Index)
		r[index*2+1] = k.Value
	}
	return r
}
